package org.fastsyncer.core.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.NamingException;

import org.apache.commons.lang.StringUtils;
import org.fastsyncer.common.constant.CommonConstant;
import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.constant.MappingConstant;
import org.fastsyncer.common.entity.Mapping;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.common.util.ApplicationUtil;
import org.fastsyncer.common.util.UUIDUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class MappingTaskUtil {

    private static Logger logger = LoggerFactory.getLogger(MappingTaskUtil.class);

    public static MappingTask parse(String mapping) throws JSONException, InstantiationException, IllegalAccessException, ClassNotFoundException, NamingException {
        MappingTask mappingTask = new MappingTask();
        // 1.解析连接器配置
        JSONObject rel = new JSONObject(mapping);

        // 2.获取mapping基本信息
        parseBase(rel, mappingTask);

        // 3.解析过滤条件
        parseQuery(rel, mappingTask);

        // 4.解析高级配置
        parsePolicies(rel, mappingTask);

        // 5.解析驱动信息
        ParseDriver.parseDriver(rel, mappingTask);

        // 6.解析转换策略
        parseConvertor(rel, mappingTask);
        return mappingTask;
    }

    /**
     * 解析基本配置
     * @param mappingTask
     * @param rel
     * @throws JSONException
     */
    private static void parseBase(JSONObject rel, MappingTask mappingTask) throws JSONException {
        // 映射关系配置是否启用
        String id = rel.isNull("id") ? UUIDUtil.getUUID() : rel.getString("id");
        mappingTask.setId(id);
        mappingTask.setEnable(rel.getBoolean("enable"));
        // 映射关系配置名称
        mappingTask.setName(rel.getString("name"));
        // 应用系统信息
        mappingTask.setAppId("all");
        if (!rel.isNull("appId")) {
            mappingTask.setAppId(rel.getString("appId"));
        }
        if (!rel.isNull("appName")) {
            mappingTask.setAppName(rel.getString("appName"));
        }
        // 性能配置
        // 每次执行任务总数
        int maxTask = rel.isNull("maxTask") ? Integer.parseInt(ApplicationUtil.getKey(CommonConstant.WORKER_TASK_MAX_NUMBER)) :rel.getInt("maxTask");
        mappingTask.setMaxTask(maxTask);
        // 每次批量执行数
        int batchNum = rel.isNull("batchNum") ? Integer.parseInt(ApplicationUtil.getKey(CommonConstant.WORKER_BATCH_NUMBER)) :rel.getInt("batchNum");
        mappingTask.setBatchNum(batchNum);
        // 线程数
        int threadNum = rel.isNull("threadNum") ? Integer.parseInt(ApplicationUtil.getKey(CommonConstant.WORKER_THREAD_NUMBER)) :rel.getInt("threadNum");
        mappingTask.setThreadNum(threadNum);
        // 驱动模式
        mappingTask.setModel(rel.getString("model"));
    }

    /**
     * 解析转换器配置
     * @param rel
     * @param mappingTask
     * @throws JSONException
     */
    private static void parseConvertor(JSONObject rel, MappingTask mappingTask) throws JSONException {
        // 解析转换器配置
        Mapping mapping = mappingTask.getTargetMapping();

        // 获取JSON转换配置
        JSONObject mp = rel.getJSONObject("targetMapping");
        // 如果没有配置转换就跳过
        if (mp.isNull("convertor")) {
            return;
        }

        JSONObject convertorJson = mp.getJSONObject("convertor");
        // 获取当前目标源转换属性名称,ID、USERNAME
        JSONArray names = convertorJson.names();
        if (names == null) {
            return;
        }
        int nLen = names.length();
        if (nLen < 1) {
            return;
        }

        // 定义转换器
        Map<String, List<Map<String, String[]>>> convertor = new HashMap<String, List<Map<String, String[]>>>();
        for (int j = 0; j < nLen; j++) {
            // 属性名,ID
            String attrName = names.getString(j);
            // 获取当前属性的转换方式,"ID": [["prepend":["这是前缀"],"append":["这是后缀"]]
            JSONArray types = convertorJson.getJSONArray(attrName);
            // 解析属性转换类型
            List<Map<String, String[]>> oprs = parseConvertOprs(types);
            // 放进转换器
            convertor.put(attrName, oprs);
        }

        // 保存目标源的转换配置
        mapping.setConvertor(convertor);

    }

    // 解析属性的转换类型
    private static List<Map<String, String[]>> parseConvertOprs(JSONArray types) throws JSONException {
        // 转换类型prepend、replace、append
        if (types == null) {
            logger.error("Conversion is empty!");
            return null;
        }
        int nLen = types.length();
        if (nLen < 1) {
            logger.error("Conversion is empty!");
            return null;
        }

        // 定义属性的转换方式
        List<Map<String, String[]>> oprs = new ArrayList<>();
        for (int i = 0; i < nLen; i++) {
            // 获取处理对象 {"prepend": [ "这是前缀"]}
            JSONObject handle = types.getJSONObject(i);
            JSONArray names = handle.names();
            int len = names.length();
            if (len < 1) {
                continue;
            }
            // 获取处理方式 prepend
            String method = names.getString(0);
            JSONArray oprArr = handle.getJSONArray(method);
            int oLen = oprArr.length();
            String[] arr = new String[oLen];
            for (int j = 0; j < oLen; j++) {
                arr[j] = oprArr.getString(j);
            }
            // 将处理对象转换为map,放入list
            Map<String, String[]> map = new HashMap<>();
            map.put(method, arr);
            oprs.add(map);
        }
        return oprs;
    }

    // 解析所有的过滤条件
    private static void parseQuery(JSONObject rel, MappingTask mappingTask) throws JSONException {
        Map<String, List<Map<String, String>>> querys = new HashMap<String, List<Map<String, String>>>();
        JSONObject query = rel.getJSONObject("query");

        // 解析And过滤条件
        List<Map<String, String>> addList = parseQuery(query.getJSONArray(ConnectorConstant.OPERTION_QUERY_AND));
        querys.put(ConnectorConstant.OPERTION_QUERY_AND, addList);

        // 解析Or过滤条件
        List<Map<String, String>> orList = parseQuery(query.getJSONArray(ConnectorConstant.OPERTION_QUERY_OR));
        querys.put(ConnectorConstant.OPERTION_QUERY_OR, orList);

        // 保存解析条件
        mappingTask.setQuery(querys);
    }

    // 解析过滤条件
    private static List<Map<String, String>> parseQuery(JSONArray querys) throws JSONException {
        // 解析过滤条件
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        int qLen = querys.length();
        for (int i = 0; i < qLen; i++) {
            Map<String, String> q = new HashMap<String, String>();
            JSONObject f = (JSONObject) querys.get(i);
            q.put("name", f.getString("name"));
            q.put("operator", f.getString("operator"));
            q.put("value", f.getString("value"));
            list.add(q);
        }
        return list;
    }

    // 解析策略
    private static void parsePolicies(JSONObject rel, MappingTask mappingTask) throws JSONException {
        // 清空策略
        mappingTask.setPolicy(new HashMap<>());
        JSONObject policy = rel.getJSONObject("policy");
        // 解析增量策略
        parsePolicyIncrement(policy, mappingTask);
        // 解析转换策略
        parsePolicyConvert(policy, mappingTask);
    }

    /**
     * 解析增量策略
     * @param policy
     * @param mappingTask
     * @throws JSONException
     */
    private static void parsePolicyIncrement(JSONObject policy, MappingTask mappingTask) throws JSONException {

        if (!policy.isNull(MappingConstant.POLICY_INCREMENT)) {
            JSONObject policyInc = (JSONObject) policy.get(MappingConstant.POLICY_INCREMENT);
            HashMap<String, String> incMap = new HashMap<>();

            String model = policyInc.getString("model");
            if (MappingConstant.POLICY_INCREMENT_MODEL_QUARTZ.equals(model)) {
                incMap.put("quartzCron", policyInc.getString("quartzCron"));
                incMap.put("quartzFiled", policyInc.getString("quartzFiled"));
                incMap.put("quartzEvent", policyInc.getString("quartzEvent"));
                incMap.put("quartzEventInsert", policyInc.getString("quartzEventInsert"));
                incMap.put("quartzEventUpdate", policyInc.getString("quartzEventUpdate"));
                incMap.put("quartzEventDelete", policyInc.getString("quartzEventDelete"));
                incMap.put("scnPos", policyInc.getString("scnPos"));
                if(!policyInc.isNull("tableLabel")){
                    incMap.put("tableLabel", policyInc.getString("tableLabel"));
                }
            } else {
                // 增量类型
                String type = policyInc.getString("type");
                incMap.put("type", type);
                switch (type) {
                case MappingConstant.POLICY_INCREMENT_MYSQL:
                    break;
                case MappingConstant.POLICY_INCREMENT_ORACLE:
                    // 如果是oracle增量配置
                    incMap.put("dictionary", policyInc.getString("dictionary"));
                    break;
                case MappingConstant.POLICY_INCREMENT_SQL_MYSQL:
                    // 如果是sqlMysql增量配置
                    incMap.put("table", policyInc.getString("table").toUpperCase());
                    incMap.put("tableLabel", policyInc.getString("tableLabel").toUpperCase());
                    break;
                case MappingConstant.POLICY_INCREMENT_SQL_ORACLE:
                    // 如果是sqlOracle增量配置
                    incMap.put("dictionary", policyInc.getString("dictionary"));
                    break;
                case MappingConstant.POLICY_INCREMENT_LDAP:
                    // 如果是ldap增量配置
                    break;
                case MappingConstant.POLICY_INCREMENT_WS:
                    // 如果是webservice增量配置
                    break;
                default:
                    break;
                }
            }
            // 默认驱动策略为不可用
            incMap.put("enable", policyInc.getString("enable"));
            incMap.put("model", model);
            // 设置增量配置
            mappingTask.getPolicy().put(MappingConstant.POLICY_INCREMENT, incMap);
        }
    }

    /**
     * 解析转换策略
     * @param policy
     * @param mappingTask
     * @throws JSONException
     */
    private static void parsePolicyConvert(JSONObject policy, MappingTask mappingTask) throws JSONException {
        if (!policy.isNull(MappingConstant.POLICY_CONVERT)) {
            JSONObject policyConvert = (JSONObject) policy.get(MappingConstant.POLICY_CONVERT);
            String className = policyConvert.getString("className");
            if (StringUtils.isBlank(className)) {
                return;
            }
            HashMap<String, String> convertMap = new HashMap<>();
            convertMap.put("className", className);
            // 设置转换配置
            mappingTask.getPolicy().put(MappingConstant.POLICY_CONVERT, convertMap);
        }
    }

}
